package cn.lyjuan.payment.third.base.pay.chl;


import cn.lyjuan.payment.third.base.pay.enums.SimpleChlEnum;
import cn.lyjuan.payment.third.base.pay.vo.req.*;
import cn.lyjuan.payment.third.base.pay.vo.res.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 支付渠道借口，包含 生成支付请求 URL，回调/通知验证
 *
 * @param <ChlCnfT>      渠道配置信息
 * @param <PayReqT>      交易请求信息
 * @param <NotifyReqT>   支付平台异步通知交易状态的信息
 * @param <QueryReqT>    查询交易状态的信息
 * @param <TransferReqT> 转账信息
 * @param <PayResT>      交易请求响应信息
 */
public interface IPayChl<
        ChlCnfT extends ChlCnf
        , PayReqT extends PayReq.IPayReq
        , NotifyReqT extends NotifyReq.INotifyReq
        , QueryReqT extends QueryReq.IQueryReq
        , TransferReqT extends TransferReq.ITransferReq
        , PayResT> {
    /**
     * 处理的渠道类型
     *
     * @return
     */
    SimpleChlEnum chl();

    /**
     * 封装交易请求参数
     *
     * @param params
     * @return
     */
    BaseRes checkPayParams(PayReqT params);

    /**
     * 检查转账参数
     *
     * @param params params
     * @return BaseRes
     */
    BaseRes checkTransferParams(TransferReqT params);

    /**
     * 封装交易查询参数
     *
     * @param params
     * @return
     */
    QueryReqT parseQueryParams(Map<String, String> params);

    /**
     * 封闭交易通知请求参数
     *
     * @return
     */
    NotifyReqT parseNotifyParams(HttpServletRequest req);

    /**
     * 下单
     *
     * @param req 支付信息
     * @return 返回下单之后的交易信息
     */
    PayRes<PayResT> order(PayReq<PayReqT> req, ChlCnfT cnf);

    /**
     * 转账
     *
     * @param req 转账信息
     * @return 返回下单之后的交易信息
     */
    TransferRes<PayResT> transfer(TransferReq<TransferReqT> req, ChlCnfT cnf);

    /**
     * 处理交易的异步通知
     *
     * @param req 通知传递信息
     * @param cnf 支付渠道配置信息
     * @return 返回处理结果及交易是否成功信息
     */
    NotifyRes notifyStatus(NotifyReq<NotifyReqT> req, ChlCnfT cnf);

    /**
     * 查询订单状态，用于更新支付记录
     * 如果支付平台有查询接口，则去查询（支付平台也可能返回未知）；否则返回未知状态
     *
     * @param req 查询信息
     * @param cnf 支付渠道配置信息
     */
    QueryRes queryStatus(QueryReq<QueryReqT> req, ChlCnfT cnf);

    /**
     * 退款
     *
     * @param selfRefundNo app方退款订单号
     * @param localNo
     * @param amt
     * @param cnf
     * @return RefundRes
     */
    RefundRes orderRefund(String selfRefundNo, String localNo, Integer totalAmt, Integer amt, ChlCnfT cnf);
}
